package com.automapper.sqlfragment.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;

import com.automapper.criterion.Criterion;
import com.automapper.criterion.ExpressionContext;
import com.automapper.criterion.SimpleExpression;
import com.automapper.sqlfragment.TableFragment;
import com.automapper.utils.ObjectFacade;

public class SubQuerySqlFragment implements TableFragment {
	
	private ExpressionContext context;
	private ObjectFacade objectFacade;
	private String table;
	private String alias;
	private Map<String, Object> map = new HashMap<>();
	
	public SubQuerySqlFragment(ExpressionContext context, ObjectFacade objectFacade,
			String table, String alias) {
		this.context = context;
		this.objectFacade = objectFacade;
		this.table = table;
		this.alias = alias;
	}

	/**
	 * 拼装子查询sql
	 */
	@Override
	public String getTableFragment() throws Exception {
		List<Criterion> removeCriterion = new ArrayList<>();
		List<Criterion> expressionList = context.getExpressionList();
		
		StringBuilder sql = new StringBuilder();
		List<String> columns = objectFacade.getColumnNames();
		sql.append(" (select ")
			.append(StringUtils.join(columns.toArray(), ","))
			.append(" from ")
			.append(table)
			.append(" where 1 = 1 ");
			
		for (Criterion expression : expressionList) {
			List<String> aliases = expression.getAliase();
			if (!(expression instanceof SimpleExpression)) {
				continue;
			}
			
			if (aliases.size() == 1 && aliases.contains(alias)) {
				removeCriterion.add(expression);
				String sqlFragment = StringUtils.substringAfter(expression.toSqlString(), ".");
				sql.append(" and ").append(sqlFragment);
				map.putAll(expression.getValues());
			}
		}
		
		if (context.getPageExpression() != null) {
			// 拼装分页
			sql.append(" " + context.getPageExpression().toSqlString());
			// 将分页对象设为null，防止生成sql再次进行分页
			context.setPageExpression(null);
		}
		
		sql.append(") ").append(alias);
		context.getExpressionList().removeAll(removeCriterion);
		return sql.toString();
	}
}
